<template>
    <!--  数据交互的过程中因为js存储和修改限制，所以跳过vue官方推荐的一对一的数据传递形式，选用了obj传递  -->
    <el-form
        ref="formDataRef"
        :model="formData"
        :rules="rules"
        :label-width="labelWidth"
        class="ruleForm form_reset_css relative"
        :size="formSize"
        status-icon
        :style="`height:${showFlag?48: formHeight}px;`"
    >
        <!--    公共form集成区域    -->
        <div class="tw" id="formContentDom" ref="formContent">
            <div class="tw_form_content" :style="!isFormBnts?'width: 100%':''" :span="20">
                <el-row>
                    <template v-if="lists.length<=foldNumber">
                        <template  v-for="(item, i) in lists" :key="i" >
                            <el-col v-if="!item.hide" :span="item.col || 6" :offset="item.offset || 0">
                                <el-form-item v-if="item.slot" :label="item.label" :label-width="item.labelWidth?item.labelWidth:labelWidth" :prop="item.key">
                                    <slot :name="item.key"></slot>
                                </el-form-item>
                                <component v-else ref="allFormItem" :is="objComponent[item.type] || objComponent['twInput']" :formData="formData" :tabindex="i"
                                           :item="item" @txtChange="submitForm(formDataRef)" @tapClick="tapClick"></component>
                            </el-col>
                        </template>
                    </template>
                    <template v-else>
                        <template v-for="(item,i) in foldNumber" :key="i" >
                            <el-col v-if="!lists[i].hide" :span="lists[i].col || 6" :offset="lists[i].offset || 0">
                                <el-form-item v-if="lists[i].slot" :label="lists[i].label" :prop="lists[i].key">
                                    <slot :name="lists[i].key"></slot>
                                </el-form-item>
                                <component v-else ref="allFormItem" :is="objComponent[lists[i].type] || objComponent['twInput']" :formData="formData"  :tabindex="i" :item="lists[i]" @txtChange="submitForm(formDataRef)" @tapClick="tapClick"></component>
                            </el-col>
                        </template>
                        <transition name="el-zoom-in-top">
                            <el-col :span="24" v-show="!showFlag">
                                <el-row>
                                    <template v-for="(item, i) in lists.length-foldNumber" :key="i">
                                        <el-col  v-if="!lists[i+foldNumber].hide" :span="lists[i+foldNumber].col || 6" :offset="lists[i+foldNumber].offset || 0">
                                            <el-form-item v-if="lists[i+foldNumber].slot" :label="lists[i+foldNumber].label" :prop="lists[i+foldNumber].key">
                                                <slot :name="lists[i+foldNumber].key"></slot>
                                            </el-form-item>
                                            <component v-else ref="allFormItem" :is="objComponent[lists[i+foldNumber].type] || objComponent['twInput']" :formData="formData" :item="lists[i+foldNumber]" @txtChange="submitForm(formDataRef)" @tapClick="tapClick" :tabindex="i"></component>
                                        </el-col>
                                    </template>
                                </el-row>
                            </el-col>
                        </transition>
                    </template>
                </el-row>
            </div>
            <div class="tw_form_btns" v-if="isFormBnts">
                <div class="form_btns tw_cr">
                    <div class="pr20">
                        <el-button :icon="Search" type="primary" @click="submitForm(formDataRef)">搜索</el-button>
                        <el-button :icon="Refresh" @click="resetForm(formDataRef)"></el-button>
                        <el-button v-if="lists.length>foldNumber" :icon="Filter" @click="onShowAllForm"></el-button>
                    </div>
                </div>
            </div>
        </div>
    </el-form>
</template>

<script setup lang="tsx" name="TwForm">
import {Search, Refresh, Filter,} from '@element-plus/icons-vue'
import twInput from "./components/twInput/index.vue"
import twInputNumber from "./components/twInputNumber/index.vue"
import TwSelect from "./components/twSelect/index.vue"
import twDate from "./components/twDate/index.vue"
import twDate1 from "./components/twDate1/index.vue"
import twTime from "./components/twTime/index.vue"
import twSwitch from "./components/twSwitch/index.vue"
import twCheckbox from "./components/twCheckbox/index.vue"
import twRadio from "./components/twRadio/index.vue"
import twCascader from "./components/twCascader/index.vue"
import twEsDate from "./components/twEsDate/index.vue"
import twEsNumber from "./components/twEsNumber/index.vue"
import twEsNumberExt from "./components/twEsNumberExt/index.vue"
import twAllSelect from "./components/twAllSelect/index.vue";
defineOptions({
    name: 'TwForm'
})

// @ts-ignore
let { proxy } =  getCurrentInstance()
// @ts-ignore
let {lists, rules, formData, labelWidth, isFormBnts, beforeChange} = defineProps({
    lists: {type: Array, default: () => []},
    foldNumber: { type: Number, default: 4},
    rules: Object,
    formData: Object,
    labelWidth: { type: String, default: '120px'},
    isFormBnts: { type: Boolean, default: true},
    beforeChange: { type: Function}
})

// @ts-ignore
let objComponent = shallowRef({
    'twInput': twInput,
    'number': twInputNumber,
    'select': TwSelect,
    'date': twDate,
    'date1': twDate1,
    'time': twTime,
    'switch': twSwitch,
    'checkbox': twCheckbox,
    'radio': twRadio,
    'cascader': twCascader,
    'esDate': twEsDate,
    'allSelect': twAllSelect,
    'esNumber': twEsNumber,
    'esNumberExt': twEsNumberExt,
    
})

// @ts-ignore
const formSize = $ref('default')
// @ts-ignore
const formDataRef = $ref(null)
// @ts-ignore
let showFlag = $ref(true)
// @ts-ignore
let formContent = $ref(null)
// @ts-ignore
let formHeight = $ref(null)
// @ts-ignore
const allFormItem = $ref(null)
// @ts-ignore
const emits = defineEmits(['submitForm', 'onFormflag', 'changeOrg', 'reset', 'orgChange', 'selectChange', 'dateChange', 'checkChange', 'timeChange', 'resetForm'])
// 提交-搜索
const submitForm = async (formEl) => {
    if (!formEl) return
    // @ts-ignore
    formEl.validate((valid) => {
        if (valid) {
            if(beforeChange){
                beforeChange(formData)
            }else {
                emits('submitForm', formData)
            }
        } else {
            // @ts-ignore
            ElMessage.error('这是错误输入')
        }
    })
}

// 分发组件内部事件
const tapClick = (key, data: {resetIndex:any})=>{
    switch (key) {
        case 'reset': {
            allFormItem[data.resetIndex].reset()
        }
    }
    emits(key, data)
}

// 展开折叠
const onShowAllForm = async ()=>{
    showFlag = !showFlag
    // @ts-ignore
    nextTick(()=>{
        setHeight(()=>{
            emits('onFormflag', showFlag)
        })
    })
}

// setTimeout(()=>{
    onShowAllForm()
// },1000)

const notNull = (flag) => {
    return flag !== null && flag !== '' && flag !== 'null' && flag !== undefined
}

const setHeight = (callback)=>{
    formHeight = document.getElementById('formContentDom').clientHeight || 'auto'
    if(showFlag && formHeight > 52){
        setTimeout(()=>{
            setHeight(callback)
        }, 200)
    }else  {
        callback(formHeight)
    }
}

const validate = () => {
    formDataRef.validate()
}

// 重置form
const resetForm = (formEl) => {
    if (!formEl) return
    formDataRef.resetFields()
    emits('resetForm', formData)
    
    if(lists.length>0){
        lists.forEach((item, i)=>{
            if(lists[i].type == 'select'){
                allFormItem[i].clearKeyword()
            }
        })
    }
}

defineExpose({validate, resetForm})
</script>



<style scoped lang="scss">
.ruleForm {
    border-bottom: 1px solid var(--tw-color-border);
    .tw_form_content { width: calc(100% - 240px); }
    .tw_form_btns { width: 240px; }
}
</style>
